/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { ArkFile, AstTreeUtils, ts } from 'arkanalyzer';
import Logger, { LOG_MODULE_TYPE } from 'arkanalyzer/lib/utils/logger';
import { BaseChecker, BaseMetaData } from '../BaseChecker';
import { Rule, Defects, MatcherTypes, MatcherCallback, FileMatcher } from '../../Index';
import { RuleListUtil } from '../../utils/common/DefectsList';
import { IssueReport } from '../../model/Defects';
import { RuleFix } from '../../model/Fix';

const logger = Logger.getLogger(LOG_MODULE_TYPE.HOMECHECK, 'BraceStyleCheck');

type stringOpt = '1tbs' | 'stroustrup' | 'allman';

type Options = [
    stringOpt,
    {
        /* true（默认 false）允许块的开始和结束括号位于同一行 */
        allowSingleLine: boolean;
    }
];

interface WarnInfo {
    line: number;
    startCol: number;
    endCol: number;
    message: string;
};

type MessageInfo = {
    nextLineIsOpen: string,
    sameLineIsOpen: string,
    blockIsSameLine: string,
    nextLineIsClose: string,
    singleLineIsClose: string,
    sameLineIsClose: string
};

export class BraceStyleCheck implements BaseChecker {
    public rule: Rule;
    private defaultOptions: Options = ['1tbs', { 'allowSingleLine': false }];
    public defects: Defects[] = [];
    public issues: IssueReport[] = [];
    private filePath: string = '';
    // 缓存常用的 SyntaxKind 判断结果
    private readonly specialBlockKinds = new Set([
        ts.SyntaxKind.ElseKeyword,
        ts.SyntaxKind.CatchKeyword,
        ts.SyntaxKind.FinallyKeyword
    ]);

    // 使用 WeakMap 缓存节点的行号信息，避免重复计算
    private readonly lineCache = new WeakMap<ts.Node, number>();

    // 缓存已处理过的节点信息
    private readonly processedNodes = new WeakMap<ts.Node, {
        indent: string;
        isClassOrInterface: boolean;
    }>();

    public metaData: BaseMetaData = {
        severity: 1,
        ruleDocPath: 'docs/brace-style-check.md',
        description: 'Enforce consistent brace style for blocks.',
    };

    public messages: MessageInfo = {
        nextLineIsOpen: 'Opening curly brace does not appear on the same line as controlling statement.',
        sameLineIsOpen: 'Opening curly brace appears on the same line as controlling statement.',
        blockIsSameLine: 'Statement inside of curly braces should be on next line.',
        nextLineIsClose: 'Closing curly brace does not appear on the same line as the subsequent block.',
        singleLineIsClose: 'Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.',
        sameLineIsClose: 'Closing curly brace appears on the same line as the subsequent block.'
    };

    private fileMatcher: FileMatcher = {
        matcherType: MatcherTypes.FILE,
    };

    public registerMatchers(): MatcherCallback[] {
        const fileMatcherCb: MatcherCallback = {
            matcher: this.fileMatcher,
            callback: this.check,
        };

        return [fileMatcherCb];
    };

    private getDefaultOption(): Options {
        if (this.rule && this.rule.option && this.rule.option.length > 0) {
            return this.rule.option as Options;
        }
        return ['1tbs', { 'allowSingleLine': false }];
    };

    public check = (target: ArkFile): void => {
        try {
            this.defaultOptions = this.getDefaultOption();
            let code = target.getCode();
            if (!code) {
                return;
            }
            this.filePath = target.getFilePath();

            if (this.filePath.endsWith('.ets')) {
                //   如果是ets文件需要将'struct ' 关键字替换为 ' class '在进行检查
                code = code.replace('struct ', ' class ');
            }

            const sourceFile = AstTreeUtils.getASTNode(target.getName(), code);
            this.checkAllBlocks(sourceFile);

        } catch (error) {
            logger.error(`Error occurred while checking file: ${target.getFilePath()}, Error: ${error}`);
        };
    };

    /**
     * 通用的 AST 节点遍历函数
     * @param sourceFile 源文件
     * @param callback 遍历每个节点时执行的回调函数
     */
    private traverseAST(sourceFile: ts.SourceFile, callback: (node: ts.Node) => void) {
        const traverse = (node: ts.Node): void => {
            callback(node);
            ts.forEachChild(node, traverse);
        };
        traverse(sourceFile);
    };

    private findBraceTokens(node: ts.Node, sourceFile: ts.SourceFile): [ts.Node | null, ts.Node | null] {
        let openBrace: ts.Node | null = null;
        let closeBrace: ts.Node | null = null;

        // 遍历所有子token
        const tokens = node.getChildren(sourceFile);
        for (const token of tokens) {
            if (token.kind === ts.SyntaxKind.OpenBraceToken) {
                openBrace = token;
            };
            if (token.kind === ts.SyntaxKind.CloseBraceToken) {
                closeBrace = token;
            };
        };

        return [openBrace, closeBrace];
    };

    // 检查所有花括号的位置
    checkAllBlocks(sourceFile: ts.SourceFile): void {
        this.traverseAST(sourceFile, (node): void => {
            if (ts.isBlock(node) ||
                ts.isClassDeclaration(node) ||
                ts.isInterfaceDeclaration(node) ||
                ts.isEnumDeclaration(node) ||
                ts.isModuleDeclaration(node) ||
                ts.isNamespaceExportDeclaration(node) ||
                ts.isModuleBlock(node) ||
                ts.isCaseBlock(node) ||
                ts.isSwitchStatement(node)) {

                const [openBrace, closeBrace] = this.findBraceTokens(node, sourceFile);

                if (openBrace && closeBrace) {
                    try {
                        this.validateCurlyPair(node, sourceFile, openBrace, closeBrace);
                    } catch (error) {
                        console.error(`Error checking block at position ${node.getStart()}:`, error);
                    };
                };
            };
        });
    };

    // 节点类型判断
    private nodeKindIsSpecialBlock(node: ts.Node): boolean {
        return this.specialBlockKinds.has(node.kind);
    }

    // 同行判断，使用缓存
    private isTokenOnSameLine(left: ts.Node | null, right: ts.Node | null): boolean {
        if (!left || !right) {
            return false;
        };

        const getLineNumber = (node: ts.Node): number => {
            let line = this.lineCache.get(node);
            if (line === undefined) {
                line = node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line;
                this.lineCache.set(node, line);
            };
            return line;
        };

        return getLineNumber(left) === getLineNumber(right);
    };

    private validateCurlyPair(
        node: ts.Node,
        sourceFile: ts.SourceFile,
        openingCurlyToken: ts.Node | ts.Token<ts.SyntaxKind.OpenBraceToken>,
        closingCurlyToken: ts.Node | ts.Token<ts.SyntaxKind.CloseBraceToken>
    ): void {
        // 确保所有token都有效
        if (!openingCurlyToken || !closingCurlyToken) {
            return;
        };

        const style = this.defaultOptions[0];
        const allowSingleLine = this.defaultOptions[1].allowSingleLine;
        const isSingleLine = this.isTokenOnSameLine(openingCurlyToken, closingCurlyToken);

        // 获取左花括号前的token 
        const tokenBeforeOpeningCurly = this.findTokenBeforeOpeningCurly(openingCurlyToken, sourceFile);
        // 获取右花括号前的token 
        const tokenBeforeClosingCurly = this.findTokenBeforeClosingCurly(closingCurlyToken, sourceFile);
        // 获取左花括号后的token 
        const tokenAfterOpeningCurly = this.findTokenAfterOpeningCurly(openingCurlyToken, sourceFile);
        // 获取右花括号后的token 
        const tokenAfterClosingCurly = this.findTokenAfterClosingCurly(closingCurlyToken, sourceFile);

        // 检查是否是特殊块（else 或 catch 或 finally）
        const isSpecialBlock = tokenAfterClosingCurly && this.nodeKindIsSpecialBlock(tokenAfterClosingCurly);

        // 检查是否是完全单行的情况
        const isCompletelyOneLine = allowSingleLine &&
            ((style === '1tbs' && (!isSpecialBlock || this.isTokenOnSameLine(closingCurlyToken, tokenAfterClosingCurly))) ||
                (style === 'stroustrup' && !isSpecialBlock)) &&
            isSingleLine &&
            tokenBeforeOpeningCurly &&
            this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken);

        // 如果是允许的单行情况，跳过检查
        if (isCompletelyOneLine) {
            return;
        };

        // 检查类声明和静态块
        if (ts.isClassDeclaration(node) || ts.isClassStaticBlockDeclaration(node)) {
            this.validateClassBraces(
                node, style, allowSingleLine, isSingleLine,
                tokenBeforeOpeningCurly, tokenAfterOpeningCurly,
                tokenBeforeClosingCurly, tokenAfterClosingCurly,
                openingCurlyToken, closingCurlyToken, sourceFile
            );
            return;
        };

        // 检查左花括号位置
        this.validateOpeningBrace(
            node, style, allowSingleLine, isSingleLine,
            tokenBeforeOpeningCurly, openingCurlyToken,
            sourceFile
        );

        // 检查块内语句
        this.validateBlockStatements(
            node, style, allowSingleLine, isSingleLine,
            tokenAfterOpeningCurly, openingCurlyToken,
            isSpecialBlock, sourceFile
        );

        // 检查右花括号
        this.validateClosingBrace(
            node, style, allowSingleLine, isSingleLine,
            tokenBeforeClosingCurly, closingCurlyToken,
            tokenAfterClosingCurly, openingCurlyToken,
            isSpecialBlock, sourceFile
        );
    };

    private validateClassBraces(
        node: ts.Node,
        style: stringOpt,
        allowSingleLine: boolean,
        isSingleLine: boolean,
        tokenBeforeOpeningCurly: ts.Node | null,
        tokenAfterOpeningCurly: ts.Node | null,
        tokenBeforeClosingCurly: ts.Node | null,
        tokenAfterClosingCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        closingCurlyToken: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        // 如果是允许单行且确实是单行的情况，跳过检查
        if (tokenBeforeOpeningCurly &&
            this.shouldSkipClassValidation(allowSingleLine, isSingleLine, tokenBeforeOpeningCurly, openingCurlyToken)) {
            return;
        }

        // 检查开始花括号位置
        this.validateClassOpeningBrace(style, tokenBeforeOpeningCurly, tokenAfterOpeningCurly, openingCurlyToken, node, sourceFile);
        // 检查结束花括号位置
        this.validateClassClosingBrace(allowSingleLine, openingCurlyToken, closingCurlyToken, tokenBeforeClosingCurly, node, sourceFile);
    };

    private shouldSkipClassValidation(
        allowSingleLine: boolean,
        isSingleLine: boolean,
        tokenBeforeOpeningCurly: ts.Node,
        openingCurlyToken: ts.Node
    ): boolean {
        return allowSingleLine && isSingleLine && this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken);
    };

    private validateClassOpeningBrace(
        style: stringOpt,
        tokenBeforeOpeningCurly: ts.Node | null,
        tokenAfterOpeningCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (style === 'allman') {
            this.handleAllmanOpeningBrace(tokenBeforeOpeningCurly, tokenAfterOpeningCurly, openingCurlyToken, node, sourceFile);
        } else {
            this.handleOtherStyleOpeningBrace(tokenBeforeOpeningCurly, tokenAfterOpeningCurly, openingCurlyToken, node, sourceFile);
        }
    }

    private handleAllmanOpeningBrace(
        tokenBeforeOpeningCurly: ts.Node | null,
        tokenAfterOpeningCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (tokenAfterOpeningCurly && this.isTokenOnSameLine(tokenAfterOpeningCurly, openingCurlyToken)) {
            this.addBraceStyleIssue(openingCurlyToken, this.messages.blockIsSameLine, sourceFile, node);
        }
        if (tokenBeforeOpeningCurly && this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken)) {
            this.addBraceStyleIssue(openingCurlyToken, this.messages.sameLineIsOpen, sourceFile, node);
        }
    }

    private handleOtherStyleOpeningBrace(
        tokenBeforeOpeningCurly: ts.Node | null,
        tokenAfterOpeningCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (tokenAfterOpeningCurly && this.isTokenOnSameLine(tokenAfterOpeningCurly, openingCurlyToken)) {
            this.addBraceStyleIssue(openingCurlyToken, this.messages.blockIsSameLine, sourceFile, node);
        }
        if (tokenBeforeOpeningCurly && !this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken)) {
            this.addBraceStyleIssue(openingCurlyToken, this.messages.nextLineIsOpen, sourceFile, node);
        }
    }

    private validateClassClosingBrace(
        allowSingleLine: boolean,
        openingCurlyToken: ts.Node,
        closingCurlyToken: ts.Node,
        tokenBeforeClosingCurly: ts.Node | null,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (!allowSingleLine || !this.isTokenOnSameLine(openingCurlyToken, closingCurlyToken)) {
            if (tokenBeforeClosingCurly && this.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurlyToken)) {
                this.addBraceStyleIssue(closingCurlyToken, this.messages.singleLineIsClose, sourceFile, node);
            }
        }
    }

    private validateOpeningBrace(
        node: ts.Node,
        style: stringOpt,
        allowSingleLine: boolean,
        isSingleLine: boolean,
        tokenBeforeOpeningCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (style === 'allman') {
            if (tokenBeforeOpeningCurly &&
                this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken) &&
                tokenBeforeOpeningCurly === openingCurlyToken) {
                this.addBraceStyleIssue(
                    openingCurlyToken,
                    this.messages.sameLineIsOpen,
                    sourceFile,
                    node
                );
            };
            // allman 风格：所有花括号都应该在新行，除非是允许的单行情况
            if (!allowSingleLine || !isSingleLine) {
                if (tokenBeforeOpeningCurly &&
                    this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken) &&
                    tokenBeforeOpeningCurly !== openingCurlyToken) {
                    this.addBraceStyleIssue(
                        openingCurlyToken,
                        this.messages.sameLineIsOpen,
                        sourceFile,
                        node
                    );
                };
            };
        } else {
            // 1tbs和stroustrup风格的处理
            if (!allowSingleLine || !isSingleLine) {
                // stroustrup风格的特殊情况：else、catch、finally等关键字后的左花括号应该新起一行
                const isStroustrupException = style === 'stroustrup' &&
                    tokenBeforeOpeningCurly?.kind === ts.SyntaxKind.CloseBraceToken;

                // 对于1tbs和stroustrup，左花括号应该和前一个token在同一行（除了stroustrup的特例）,如果tokenBeforeOpeningCurly是左花括号，说明一定换行了
                if (!isStroustrupException &&
                    tokenBeforeOpeningCurly &&
                    (!this.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurlyToken) ||
                        tokenBeforeOpeningCurly === openingCurlyToken)) {
                    this.addBraceStyleIssue(
                        openingCurlyToken,
                        this.messages.nextLineIsOpen,
                        sourceFile,
                        node
                    );
                };
            };
        };
    };

    private validateBlockStatements(
        node: ts.Node,
        style: stringOpt,
        allowSingleLine: boolean,
        isSingleLine: boolean,
        tokenAfterOpeningCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        isSpecialBlock: boolean | null,
        sourceFile: ts.SourceFile
    ): void {
        // allman 风格需要特殊处理
        if (style === 'allman' && (!allowSingleLine || !isSingleLine)) {
            if (tokenAfterOpeningCurly &&
                this.isTokenOnSameLine(tokenAfterOpeningCurly, openingCurlyToken)) {
                this.addBraceStyleIssue(
                    openingCurlyToken,
                    this.messages.blockIsSameLine,
                    sourceFile,
                    node
                );
            };
        } else if (style === '1tbs' && !allowSingleLine) {
            // 1tbs 风格：在不允许单行或是特殊块时检查
            if (tokenAfterOpeningCurly &&
                this.isTokenOnSameLine(tokenAfterOpeningCurly, openingCurlyToken)) {
                this.addBraceStyleIssue(
                    openingCurlyToken,
                    this.messages.blockIsSameLine,
                    sourceFile,
                    node
                );
            };
        } else if (style === 'stroustrup' && !allowSingleLine) {
            // stroustrup 风格且不允许单行时，检查块内语句位置
            if (tokenAfterOpeningCurly &&
                this.isTokenOnSameLine(tokenAfterOpeningCurly, openingCurlyToken)) {
                this.addBraceStyleIssue(
                    openingCurlyToken,
                    this.messages.blockIsSameLine,
                    sourceFile,
                    node
                );
            };
        };
    };

    // 检查右花括号
    private validateClosingBrace(
        node: ts.Node,
        style: stringOpt,
        allowSingleLine: boolean,
        isSingleLine: boolean,
        tokenBeforeClosingCurly: ts.Node | null,
        closingCurlyToken: ts.Node,
        tokenAfterClosingCurly: ts.Node | null,
        openingCurlyToken: ts.Node,
        isSpecialBlock: boolean | null,
        sourceFile: ts.SourceFile
    ): void {
        // 检查右花括号与前一个token的关系
        this.validateClosingBraceSameLine(tokenBeforeClosingCurly, closingCurlyToken, openingCurlyToken,
            allowSingleLine, node, sourceFile);

        // 检查右花括号与后续块的关系
        if (tokenAfterClosingCurly && (!allowSingleLine || !isSingleLine || isSpecialBlock)) {
            this.validateClosingBraceAfterToken(style, isSpecialBlock, closingCurlyToken, tokenAfterClosingCurly, node, sourceFile);
        };
    };

    private validateClosingBraceSameLine(
        tokenBeforeClosingCurly: ts.Node | null,
        closingCurlyToken: ts.Node,
        openingCurlyToken: ts.Node,
        allowSingleLine: boolean,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        const isAllmanWithSingleLine = allowSingleLine &&
            this.isTokenOnSameLine(openingCurlyToken, closingCurlyToken);

        if (tokenBeforeClosingCurly &&
            (tokenBeforeClosingCurly !== openingCurlyToken) &&
            !isAllmanWithSingleLine &&
            this.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurlyToken)) {
            this.addBraceStyleIssue(
                closingCurlyToken,
                this.messages.singleLineIsClose,
                sourceFile,
                node
            );
        }
    }

    private validateClosingBraceAfterToken(
        style: stringOpt,
        isSpecialBlock: boolean | null,
        closingCurlyToken: ts.Node,
        tokenAfterClosingCurly: ts.Node | null,
        node: ts.Node,
        sourceFile: ts.SourceFile
    ): void {
        if (style === 'allman' && isSpecialBlock &&
            this.isTokenOnSameLine(closingCurlyToken, tokenAfterClosingCurly)) {
            this.addBraceStyleIssue(
                closingCurlyToken,
                this.messages.sameLineIsClose,
                sourceFile,
                node
            );
        } else if (style === '1tbs' && isSpecialBlock !== this.isTokenOnSameLine(closingCurlyToken, tokenAfterClosingCurly)) {
            this.addBraceStyleIssue(
                closingCurlyToken,
                isSpecialBlock ? this.messages.nextLineIsClose : this.messages.sameLineIsClose,
                sourceFile,
                node
            );
        } else if (style === 'stroustrup' && this.isTokenOnSameLine(closingCurlyToken, tokenAfterClosingCurly)) {
            this.addBraceStyleIssue(
                closingCurlyToken,
                this.messages.sameLineIsClose,
                sourceFile,
                node
            );
        }
    }

    /**
     * 获取左花括号前的token
     */
    private findTokenBeforeOpeningCurly(openingCurly: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        // 获取父节点的所有子节点
        const siblings = openingCurly.parent.getChildren(sourceFile);

        // 找到左花括号的位置
        let curlyIndex = siblings.findIndex(node => node === openingCurly);

        if (!curlyIndex) {
            // 获取父节点的父节点的所有子节点
            const parentSiblings = openingCurly.parent.parent?.getChildren(sourceFile);
            if (parentSiblings) {
                // 在父层级中查找包含左花括号的节点
                curlyIndex = parentSiblings.findIndex(node =>
                    node.getChildren(sourceFile).some(child => child === openingCurly)
                );
                if (curlyIndex > 0) {
                    return parentSiblings[curlyIndex - 1];
                };
            };
            return openingCurly;
        };

        // 返回左花括号前的节点
        return siblings[curlyIndex - 1];
    };

    /**
     * 获取右花括号前的token
     */
    private findTokenBeforeClosingCurly(closingCurly: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        let prevToken: ts.Node | null = null;
        this.traverseAST(sourceFile, (node): void => {
            if (node === closingCurly) {
                return;
            }
            const lastToken = node.getLastToken(sourceFile);
            if (lastToken && lastToken.end < closingCurly.getStart()) {
                prevToken = lastToken;
            };
        });
        return prevToken;
    };

    /**
     * 获取左花括号后的token
     */
    private findTokenAfterOpeningCurly(openingCurly: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        // 获取父节点的所有子节点
        const siblings = openingCurly.parent.getChildren(sourceFile);

        // 找到左花括号的位置
        const curlyIndex = siblings.findIndex(node => node === openingCurly);

        // 如果找到左花括号且不是最后一个节点
        if (curlyIndex !== -1 && curlyIndex < siblings.length - 1) {
            // 获取下一个节点的第一个有效token
            const nextNode = siblings[curlyIndex + 1];
            return nextNode?.getFirstToken(sourceFile) || null;
        };

        return null;
    };

    // 获取父级if语句
    private getParentIfStatement(node: ts.Node): ts.IfStatement | null {
        let current = node.parent;
        while (current) {
            if (ts.isIfStatement(current)) {
                return current;
            };
            current = current.parent;
        };
        return null;
    };

    private handleIfStatement(ifStmt: ts.IfStatement, closingCurlyParent: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        // 如果当前块是if的then块
        if (ifStmt.thenStatement && closingCurlyParent === ifStmt.thenStatement) {
            // 检查是否有else或else if
            if (ifStmt.elseStatement) {
                // 查找else关键字
                const elseToken = ifStmt.getChildren(sourceFile).find(child =>
                    child.kind === ts.SyntaxKind.ElseKeyword);
                return elseToken || null;
            };
        }
        // 如果当前块是else if的then块
        else if (ifStmt.elseStatement && ts.isIfStatement(ifStmt.elseStatement) &&
            closingCurlyParent === ifStmt.elseStatement.thenStatement) {
            // 检查后续是否还有else或else if
            if (ifStmt.elseStatement.elseStatement) {
                const elseToken = ifStmt.elseStatement.getChildren(sourceFile).find(child =>
                    child.kind === ts.SyntaxKind.ElseKeyword);
                return elseToken || null;
            };
        };
        return null;
    };

    private getParentTryStatement(node: ts.Node): ts.TryStatement | null {
        let current = node.parent;
        while (current) {
            if (ts.isTryStatement(current)) {
                return current;
            };
            current = current.parent;
        };
        return null;
    };

    private handleTryStatement(tryStmt: ts.TryStatement, closingCurlyParent: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        // 如果当前块是try块
        if (closingCurlyParent === tryStmt.tryBlock) {
            if (tryStmt.catchClause) {
                const token = tryStmt.catchClause.getFirstToken(sourceFile);
                return token || null;
            } else if (tryStmt.finallyBlock) {
                const finallyToken = tryStmt.getChildren(sourceFile).find(child =>
                    child.kind === ts.SyntaxKind.FinallyKeyword);
                return finallyToken || null;
            };
        }
        // 如果当前块是catch块
        else if (tryStmt.catchClause && closingCurlyParent === tryStmt.catchClause.block) {
            if (tryStmt.finallyBlock) {
                const finallyToken = tryStmt.getChildren(sourceFile).find(child =>
                    child.kind === ts.SyntaxKind.FinallyKeyword);
                return finallyToken || null;
            };
        };
        return null;
    };

    /**
     * 获取右花括号后的token
     */
    private findTokenAfterClosingCurly(closingCurly: ts.Node, sourceFile: ts.SourceFile): ts.Node | null {
        // 主要处理逻辑
        const parentIfStmt = this.getParentIfStatement(closingCurly);
        if (parentIfStmt) {
            const nextNode = this.handleIfStatement(parentIfStmt, closingCurly.parent, sourceFile);
            if (nextNode) {
                return nextNode;
            };
        };

        const parentTryStmt = this.getParentTryStatement(closingCurly);
        if (parentTryStmt) {
            const nextNode = this.handleTryStatement(parentTryStmt, closingCurly.parent, sourceFile);
            if (nextNode) {
                return nextNode;
            };
        };

        // 如果不是特殊情况，则按照普通方式处理
        const siblings = closingCurly.parent.getChildren(sourceFile);
        const curlyIndex = siblings.findIndex(node => node === closingCurly);
        if (curlyIndex < siblings.length - 1) {
            return siblings[curlyIndex + 1];
        };

        return null;
    };

    /**
     * 获取父节点的缩进
     * @param node 当前节点
     * @returns 父节点的缩进字符串
     */
    private getParentIndent(node: ts.Node, sourceFile: ts.SourceFile): string {
        const cached = this.processedNodes.get(node);
        if (cached) {
            return cached.indent;
        };

        const parent = node.parent;
        if (!parent) {
            return '';
        };

        const lineStart = sourceFile.getPositionOfLineAndCharacter(
            sourceFile.getLineAndCharacterOfPosition(parent.getStart()).line,
            0
        );
        const lineText = sourceFile.text.substring(lineStart, parent.getStart());
        const indent = lineText.match(/^\s*/)?.[0] || '';

        const isClassOrInterface = ts.isClassDeclaration(parent) ||
            ts.isInterfaceDeclaration(parent);

        this.processedNodes.set(node, {
            indent,
            isClassOrInterface
        });

        return indent;
    };

    private handleNextLineOpen(pos: number, end: number, braceStyle: string, baseIndent: string,
        currentIndent: string, isClassOrInterface: boolean, sourceFile: ts.SourceFile): RuleFix {
        if (braceStyle === '1tbs' || braceStyle === 'stroustrup') {
            const prevTokenEnd = sourceFile.text.lastIndexOf('\n', pos);
            // 左花括号应该和控制语句在同一行
            // 需要删除从上一行末尾到当前花括号位置的所有内容（包括换行和空白）
            return {
                range: [prevTokenEnd, end],
                text: ' {'
            };
        };
        return {
            range: [pos, end],
            // 对于类声明，保持与类名对齐
            text: (isClassOrInterface ? baseIndent : currentIndent) + '{'
        };
    };

    private handleNextLineClose(pos: number, end: number, braceStyle: string, baseIndent: string,
        afterToken: ts.Node | null, isClassOrInterface: boolean): RuleFix {
        if (braceStyle === '1tbs' && afterToken && this.nodeKindIsSpecialBlock(afterToken)) {
            return { range: [end, afterToken.getStart()], text: ' ' };
        };
        return {
            range: [pos, end],
            text: '\n' + baseIndent + '}'
        };
    };

    private handleSameLineOpen(pos: number, end: number, braceStyle: string): RuleFix {
        if (braceStyle === '1tbs' || braceStyle === 'stroustrup') {
            return { range: [pos, end], text: ' {' };
        };
        return { range: [end, end], text: '\n' };
    };

    private handleSingleLineClose(pos: number, end: number, braceStyle: string, baseIndent: string,
        currentIndent: string, afterToken: ts.Node | null, isClassOrInterface: boolean): RuleFix {
        // 处理块内容与右花括号在同一行的情况
        if (braceStyle === 'stroustrup' && afterToken && this.nodeKindIsSpecialBlock(afterToken)) {
            return {
                range: [pos, pos],
                text: '\n' + (isClassOrInterface ? baseIndent : currentIndent)
            };
        };
        return { range: [pos, end], text: '\n' + baseIndent + '}' };
    };

    private handleSameLineClose(pos: number, end: number, braceStyle: string, baseIndent: string,
        currentIndent: string, afterToken: ts.Node | null, isClassOrInterface: boolean): RuleFix {
        // 处理右花括号与后续语句在同一行的情况
        if (braceStyle === 'stroustrup' && afterToken && this.nodeKindIsSpecialBlock(afterToken)) {
            return {
                range: [end, end],
                text: '\n' + (isClassOrInterface ? baseIndent : currentIndent)
            };
        };
        return {
            range: [pos, end],
            text: (isClassOrInterface ? baseIndent : currentIndent) + '}\n' + currentIndent
        };
    };

    private handleBlockSameLine(pos: number, end: number, braceStyle: string, baseIndent: string,
        currentIndent: string): RuleFix {
        // 处理左花括号与语句在同一行的情况
        if (braceStyle === 'allman') {
            return { range: [pos, pos], text: '\n' };
        };
        return {
            range: [pos, end],
            text: '\n' + baseIndent + '{\n' + currentIndent
        };
    };

    private ruleFix(pos: number, end: number, message: string, sourceFile: ts.SourceFile, tokenNode: ts.Node, afterToken: ts.Node | null): RuleFix {
        const braceStyle = this.defaultOptions[0];
        // 获取缓存的节点信息
        const nodeInfo = this.processedNodes.get(tokenNode) || {
            indent: this.getParentIndent(tokenNode, sourceFile),
            isClassOrInterface: ts.isClassDeclaration(tokenNode.parent) || ts.isInterfaceDeclaration(tokenNode.parent)
        };

        // 获取基础缩进
        const baseIndent = nodeInfo.indent;
        // 如果是类声明的左花括号，使用父节点的缩进
        const currentIndent = nodeInfo.isClassOrInterface ? baseIndent : baseIndent + '  ';

        switch (message) {
            case this.messages.nextLineIsOpen:
                this.handleNextLineOpen(pos, end, braceStyle, baseIndent, currentIndent, nodeInfo.isClassOrInterface, sourceFile);
            case this.messages.nextLineIsClose:
                this.handleNextLineClose(pos, end, braceStyle, baseIndent, afterToken, nodeInfo.isClassOrInterface);
            case this.messages.sameLineIsOpen:
                this.handleSameLineOpen(pos, end, braceStyle);
            case this.messages.singleLineIsClose:
                this.handleSingleLineClose(pos, end, braceStyle, baseIndent, currentIndent, afterToken, nodeInfo.isClassOrInterface);
            case this.messages.sameLineIsClose:
                this.handleSameLineClose(pos, end, braceStyle, baseIndent, currentIndent, afterToken, nodeInfo.isClassOrInterface);
            case this.messages.blockIsSameLine:
                this.handleBlockSameLine(pos, end, braceStyle, baseIndent, currentIndent);
            default:
                return { range: [-1, -1], text: '' };
        };
    };

    private addBraceStyleIssue(
        tokenNode: ts.Node,
        message: string,
        sourceFile: ts.SourceFile,
        afterToken: ts.Node | null,
    ): void {
        const position = sourceFile.getLineAndCharacterOfPosition(tokenNode.getStart());
        const startCol = position.character + 1;
        let defect = this.addIssueReport({
            line: position.line + 1,
            startCol: startCol,
            endCol: startCol,
            message,
        });

        let pos = tokenNode.getStart();
        let end = tokenNode.getEnd();
        let fix: RuleFix = this.ruleFix(pos, end, message, sourceFile, tokenNode, afterToken);
        this.issues.push({ defect, fix });
        RuleListUtil.push(defect);
    };

    private addIssueReport(warnInfo: WarnInfo): Defects {
        this.metaData.description = warnInfo.message;
        const severity = this.rule.alert ?? this.metaData.severity;
        // 创建缺陷报告
        let defect = new Defects(warnInfo.line, warnInfo.startCol, warnInfo.endCol, this.metaData.description, severity, this.rule.ruleId,
            this.filePath, this.metaData.ruleDocPath, true, false, false);
        return defect;
    };
}
